﻿using FileData.Utils.Currency;
using HtmlAgilityPack;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FileData.Currency
{
    internal class HtmlHelper
    {/// <summary>
     /// 加载HTML
     /// </summary>
     /// <param name="Htmlnode"></param>
     /// <returns></returns>
        public static HtmlDocument LoadHtml(String Htmlnode)
        {
            HtmlDocument doc = new HtmlDocument();
            try
            {
                doc.LoadHtml(Htmlnode);
            }
            catch (Exception ex)
            {
                PrintLog.Log(ex);
                PrintLog.Log("加载HTML错误 ");
            }
            return doc;
        }

        /// <summary>
        /// 清理自带属性
        /// </summary>
        /// <param name="Shtml"></param>
        /// <returns></returns>
        public static string ClearAttributes(string Shtml, string Xpath = "//div|//p|//span|//fieldset|//legend")
        {
            try
            {
                HtmlDocument htmlDocument = LoadHtml(Shtml);

                foreach (var eachNode in htmlDocument.DocumentNode.SelectNodes(Xpath))
                {
                    eachNode.Attributes.RemoveAll();
                }

                return htmlDocument.DocumentNode.InnerHtml;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }

            return "error";
        }

        /// <summary>
        /// 需要一个htmldoc 和准备用来自定义的规则
        /// </summary>
        /// <param name="shtml"></param>
        /// <param name="custom_property"></param>
        /// <returns></returns>
        public static String RemoveUnsafe(String shtml)
        {
            var htmlDoc = LoadHtml(shtml);

            htmlDoc = ChlidernDelete(htmlDoc, "script");
            htmlDoc = ChlidernDelete(htmlDoc, "style");
            htmlDoc = ChlidernDelete(htmlDoc, "//comment()");

            return htmlDoc.DocumentNode.InnerHtml;
        }

        private static HtmlDocument ChlidernDelete(HtmlDocument htmlDoc, string local_path)
        {
            try
            {
                HtmlNodeCollection htmlNodes = htmlDoc.DocumentNode.SelectNodes(local_path);
                if (htmlNodes != null)
                    foreach (HtmlNode comment in htmlNodes)
                    {
                        //(2) remove comment node itself
                        comment.ParentNode.RemoveChild(comment);
                    }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
            return htmlDoc;
        }

        /// <summary>
        /// 删除全部第三方属性
        /// </summary>
        /// <param name="Shtml"></param>
        /// <param name="Xpath"></param>
        /// <returns></returns>
        public string RemoveAllAttributes(string Shtml, string Xpath = "//div|//a|//img|//p|//span|//table|//td|//tr")
        {
            var HtmlDoc = LoadHtml(Shtml);
            var elementsWithStyleAttribute = HtmlDoc.DocumentNode.SelectNodes(Xpath);

            if (elementsWithStyleAttribute != null)
            {
                foreach (var element in elementsWithStyleAttribute)
                {
                    try
                    {
                        element.Attributes.Remove();
                    }
                    catch (Exception ex)
                    {
                        PrintLog.Log(ex);
                    }
                }
            }
            return HtmlDoc.DocumentNode.InnerHtml;
        }

        /// <summary>
        /// 清理class id style 和不安全代码
        /// </summary>
        /// <param name="Content"></param>
        /// <param name="Xpath"></param>
        /// <returns></returns>
        public string ClearContentAuto(string Content, string Xpath = "//div|//p|//img|//a|//span|//table|//td|//tr")
        {
            Content = RemoveAttributes(Content, Xpath, "class");
            Content = RemoveAttributes(Content, Xpath, "id");
            Content = RemoveAttributes(Content, Xpath, "style");
            Content = RemoveUnsafe(Content);
            Content = RemoveSrcEmpty(Content);
            Content = RemoveEmptyLable(Content);
            return Content;
        }

        /// <summary>
        /// 删除没有SRC的图片链接
        /// </summary>
        /// <param name="Content"></param>
        /// <returns></returns>
        public string RemoveSrcEmpty(string Content)
        {
            var doc = LoadHtml(Content);
            if (doc == null)
                return "";
            var nodesToRemove = doc.DocumentNode
 .SelectNodes("//img[not(string-length(normalize-space(@src)))]");
            if (nodesToRemove == null)
                return Content;
            var nodesToRemoveList = nodesToRemove.ToList();

            if (nodesToRemoveList != null)
                foreach (var node in nodesToRemove)
                    node.Remove();

            return doc.DocumentNode.InnerHtml;
        }

        /// <summary>
        /// 删除空标签
        /// </summary>
        /// <param name="Content"></param>
        /// <returns></returns>
        public string RemoveEmptyLable(string Content)
        {
            var doc = LoadHtml(Content);
            if (doc == null)
                return "";
            RemoveEmptyLable(doc.DocumentNode);
            return doc.DocumentNode.InnerHtml;
        }

        /// <summary>
        /// 删除空标签
        /// </summary>
        /// <param name="Content"></param>
        /// <returns></returns>
        public string RemoveEmptyLable(HtmlNode containerNode)
        {
            List<string> _notToRemove = new List<string>() { "br" };
            if (containerNode.Attributes.Count == 0 && !_notToRemove.Contains(containerNode.Name) && string.IsNullOrEmpty(containerNode.InnerText))
            {
                containerNode.Remove();
            }
            else
            {
                for (int i = containerNode.ChildNodes.Count - 1; i >= 0; i--)
                {
                    RemoveEmptyLable(containerNode.ChildNodes[i]);
                }
            }

            return "";
        }

        /// <summary>
        /// 删除Attribus
        /// </summary>
        /// <param name="html"></param>
        /// <param name="Xpath"></param>
        /// <param name="Attribus"></param>
        public static string RemoveAttributes(string Shtml, string Xpath, string Attribus)
        {
            var HtmlDoc = LoadHtml(Shtml);
            var elementsWithStyleAttribute = HtmlDoc.DocumentNode.SelectNodes(Xpath);

            if (elementsWithStyleAttribute != null)
            {
                foreach (var element in elementsWithStyleAttribute)
                {
                    try
                    {
                        if (element.Attributes[Attribus] != null)
                        { element.Attributes[Attribus].Remove(); }
                    }
                    catch (Exception ex)
                    {
                        PrintLog.Log(ex);
                    }
                }
            }
            return HtmlDoc.DocumentNode.InnerHtml;
        }

        /// <summary>
        /// 删除指定位置的代码并且返回String结果
        /// </summary>
        /// <param name="Shtml"></param>
        /// <param name="Xpath"></param>
        /// <returns></returns>
        public static string RemoveNode(string Shtml, String Xpath)
        {
            var HtmlDoc = LoadHtml(Shtml);
            var divs = HtmlDoc.DocumentNode.SelectNodes(Xpath);

            if (divs != null)
            {
                foreach (var tag in divs)
                {
                    tag.Remove();
                }
            }
            return HtmlDoc.DocumentNode.InnerHtml;
        }

        /// <summary>
        /// 数据鉴别时防止代码污染，返回纯文字
        /// </summary>
        /// <param name="Shtml"></param>
        /// <returns></returns>
        internal static string OutText(string Shtml)
        {
            var HtmlDoc = LoadHtml(Shtml);
            return HtmlDoc.DocumentNode.InnerText;
        }

        /// <summary>
        /// 选择并且返回HtmlNodeCollection
        /// </summary>
        /// <param name="HtmlCode"></param>
        /// <param name="Xpath"></param>
        /// <returns></returns>
        public static HtmlNodeCollection SelectNodes(String HtmlCode, String Xpath)
        {
            HtmlNodeCollection NodeCollectionvalue = null;
            try
            {
                NodeCollectionvalue = LoadHtml(HtmlCode).DocumentNode.SelectNodes(Xpath);
            }
            catch (Exception ex)
            {
                PrintLog.Log(ex);
                PrintLog.Log("选择器错误");
            }
            return NodeCollectionvalue;
        }

        /// <summary>
        ///获取选择对象的所有代码  包括对象本身
        /// </summary>
        /// <param name="HtmlCode"></param>
        /// <param name="Xpath"></param>
        /// <returns></returns>
        public static List<String> GetHtmlValueList(String HtmlCode, String Xpath)
        {
            List<string> ValueList = new List<string>();
            HtmlNodeCollection htmlNodeCollection = SelectNodes(HtmlCode, Xpath);
            if (htmlNodeCollection != null)

                foreach (HtmlNode SingleNode in htmlNodeCollection)
                {
                    ValueList.Add(SingleNode.OuterHtml);
                }
            return ValueList;
        }

        /// <summary>
        /// 获取第一个连接结果
        /// </summary>
        /// <param name="HtmlCode"></param>
        /// <param name="Xpath"></param>
        /// <returns></returns>
        public string GetFirstHtml(String HtmlCode, String Xpath)
        {
            return GetFirstValue(GetHtmlValueList(HtmlCode, Xpath));
        }

        /// <summary>
        /// 获取htmlNodeCollection里的inntext值
        /// </summary>
        /// <param name="HtmlCode"></param>
        /// <param name="Xpath"></param>
        /// <returns></returns>
        public static List<String> GetTextValueList(String HtmlCode, String Xpath)
        {
            List<string> ValueList = new List<string>();
            HtmlNodeCollection htmlNodeCollection = SelectNodes(HtmlCode, Xpath);
            if (htmlNodeCollection != null)

                foreach (HtmlNode SingleNode in htmlNodeCollection)
                {
                    ValueList.Add(SingleNode.InnerText);
                }
            return ValueList;
        }

        /// <summary>
        /// 获取第一个连接结果
        /// </summary>
        /// <param name="HtmlCode"></param>
        /// <param name="Xpath"></param>
        /// <returns></returns>
        public string GetFirstText(String HtmlCode, String Xpath)
        {
            return GetFirstValue(GetTextValueList(HtmlCode, Xpath));
        }

        /// <summary>
        /// 获取A标签里的href属性值
        /// </summary>
        /// <param name="HtmlCode"></param>
        /// <param name="Xpath"></param>
        /// <returns></returns>
        public static List<String> GetLinkVlaueList(String HtmlCode, String Xpath)
        {
            List<string> ValueList = new List<string>();
            HtmlNodeCollection htmlNodeCollection = SelectNodes(HtmlCode, Xpath);
            if (htmlNodeCollection != null)
                foreach (HtmlNode SingleNode in htmlNodeCollection)
                {
                    try
                    {
                        ValueList.Add(SingleNode.Attributes["href"].Value);
                    }
                    catch (Exception ex)
                    {
                        PrintLog.Log(ex);
                        PrintLog.Log("获取超链接错误");
                    }
                }
            return ValueList;
        }

        /// <summary>
        /// 获取第一个连接结果
        /// </summary>
        /// <param name="HtmlCode"></param>
        /// <param name="Xpath"></param>
        /// <returns></returns>
        public string GetFirstLink(String HtmlCode, String Xpath)
        {
            return GetFirstValue(GetLinkVlaueList(HtmlCode, Xpath));
        }

        /// <summary>
        /// 获取图片src的辅助方法
        /// </summary>
        /// <param name="HtmlCode"></param>
        /// <param name="Xpath"></param>
        /// <returns></returns>

        public static List<String> GetImgSrcVlaueList(String HtmlCode, String Xpath)
        {
            List<string> ValueList = new List<string>();
            HtmlNodeCollection htmlNodeCollection = SelectNodes(HtmlCode, Xpath);
            if (htmlNodeCollection != null)
                foreach (HtmlNode SingleNode in htmlNodeCollection)
                {
                    try
                    {
                        ValueList.Add(SingleNode.Attributes["src"].Value);
                    }
                    catch (Exception ex)
                    {
                        PrintLog.Log(ex);
                        PrintLog.Log("获取超链接错误");
                    }
                }
            else Console.WriteLine("使用XPTH{0}，未能获取到数据", Xpath);
            return ValueList;
        }

        /// <summary>
        /// 获取第一个图片结果
        /// </summary>
        /// <param name="HtmlCode"></param>
        /// <param name="Xpath"></param>
        /// <returns></returns>
        public string GetFirstSrc(String HtmlCode, String Xpath)
        {
            return GetFirstValue(GetImgSrcVlaueList(HtmlCode, Xpath));
        }

        /// <summary>
        /// 获取Attributes的数据
        /// </summary>
        /// <param name="HtmlCode"></param>
        /// <param name="Xpath"></param>
        /// <returns></returns>

        public static List<String> GetAttributesVlaueList(String HtmlCode, String Attributes, String Xpath)
        {
            List<string> ValueList = new List<string>();
            HtmlNodeCollection htmlNodeCollection = SelectNodes(HtmlCode, Xpath);

            if (htmlNodeCollection != null)
                foreach (HtmlNode SingleNode in htmlNodeCollection)
                {
                    try
                    {
                        ValueList.Add(SingleNode.Attributes[Attributes].Value);
                    }
                    catch (Exception ex)
                    {
                        PrintLog.Log(ex);
                        PrintLog.Log("获取GetAttributesVlaueList错误");
                    }
                }
            else Console.WriteLine("使用XPTH{0},选择{1}，未能获取到数据", Xpath, Attributes);
            return ValueList;
        }

        /// <summary>
        /// 获取第一个Attributes结果
        /// </summary>
        /// <param name="HtmlCode"></param>
        /// <param name="Xpath"></param>
        /// <returns></returns>
        public string GetFirstAttributes(String HtmlCode, String Attributes, String Xpath)
        {
            return GetFirstValue(GetAttributesVlaueList(HtmlCode, Attributes, Xpath));
        }

        /// <summary>
        /// 获取第一个值，因为htmlnode会崩溃所以要单独抽出来做
        /// </summary>
        /// <param name="list">需要liststing</param>
        /// <returns></returns>
        public static String GetFirstValue(List<String> list)
        {
            String value = "";
            foreach (string line in list)
            {
                value = line;
                break;
            }
            return value;
        }
    }
}